Hello Marek,

I have created a diffile against the 980403 release that adds
functionality to newusers for automatic handling of users with only
anonymous ftp login (using the guestgroup feature in ftpaccess, which
means that the users home directory looks like '/home/user/./'). It also
adds a commandline argument to specify an initial directory structure
for such users, with a tarball normally containing the bin,lib,etc
directories used in the chrooted environment.

I am using it to automatically create chunks of users with only ftp
access for a webserver.

I have tried to follow your coding standards and I believe it is bug
free but.. well, who knows. :) It's not much code however.

I hope you find it useful. Do what you like with it, feel free to ask if
anything is unclear.

Best rgds,
  Calle Karlsson
  ckn@kash.se

diff -uNr shadow-980403.orig/src/newusers.c shadow-980403/src/newusers.c
--- shadow-980403.orig/src/newusers.c	Fri Jan 30 00:22:43 1998
+++ shadow-980403/src/newusers.c	Fri Apr 17 16:55:33 1998
@@ -76,11 +76,35 @@
 static void
 usage(void)
 {
-	fprintf(stderr, "Usage: %s [ input ]\n", Prog);
+	fprintf (stderr, "Usage: %s [-p prototype tarfile] [ input ]\n", Prog);
+	fprintf (stderr, "The prototype tarfile is only used for users\n");
+	fprintf (stderr, "marked as anonymous ftp users. It must be a full pathname.\n");
 	exit(1);
 }
 
 /*
+ * createuserdir - create a directory and chmod it
+ */
+
+static int
+createuserdir (char * dir, int uid, int gid, int line)
+{
+	if (mkdir (dir, 0777 & ~getdef_num("UMASK", 077))) {
+		fprintf (stderr, "%s: line %d: mkdir %s failed\n",
+			 Prog, line, dir);
+		return -1;
+	}
+
+	if (chown (dir, uid, gid)) {
+		fprintf (stderr, "%s: line %d: chown %s failed\n",
+			 Prog, line, dir);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
  * add_group - create a new group or add a user to an existing group
  */
 
@@ -328,6 +352,8 @@
 main(int argc, char **argv)
 {
 	char	buf[BUFSIZ];
+	char	anonproto[BUFSIZ];
+	int	flag;
 	char	*fields[8];
 	int	nfields;
 	char	*cp;
@@ -340,12 +366,23 @@
 
 	Prog = Basename(argv[0]);
 
-	if (argc > 1 && argv[1][0] == '-')
-		usage ();
+	* anonproto = '\0';
+
+	while ((flag = getopt (argc, argv, "p:h")) != EOF) {
+		switch (flag) {
+		case 'p':
+			STRFCPY(anonproto, optarg);
+			break;
+		case 'h':
+		default:
+			usage ();
+			break;
+		}
+	}
 
-	if (argc == 2) {
-		if (! freopen (argv[1], "r", stdin)) {
-			snprintf(buf, sizeof buf, "%s: %s", Prog, argv[1]);
+	if (optind < argc) {
+		if (! freopen (argv[optind], "r", stdin)) {
+			snprintf(buf, sizeof buf, "%s: %s", Prog, argv[optind]);
 			perror (buf);
 			exit (1);
 		}
@@ -499,15 +536,36 @@
 		if (fields[6][0])
 			newpw.pw_shell = fields[6];
 
-		if (newpw.pw_dir[0] && access(newpw.pw_dir, F_OK)) {
-			if (mkdir (newpw.pw_dir,
-					0777 & ~getdef_num("UMASK", 077)))
-				fprintf (stderr, "%s: line %d: mkdir failed\n",
-					Prog, line);
-			else if (chown (newpw.pw_dir,
-					newpw.pw_uid, newpw.pw_gid))
-				fprintf (stderr, "%s: line %d: chown failed\n",
-					Prog, line);
+		if (newpw.pw_dir[0]) {
+		        char * userdir = strdup (newpw.pw_dir);
+			char * anonpart;
+			int rc;
+
+			if ((anonpart = strstr (userdir, "/./"))) {
+			        * anonpart = '\0';
+				anonpart += 2;
+			}
+			
+			if (access(userdir, F_OK))
+				rc = createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line);
+			else
+				rc = 0;
+
+			if (rc == 0 && anonpart) {
+				if (* anonproto) {
+					char cmdbuf [BUFSIZ];
+					snprintf(cmdbuf, sizeof cmdbuf,
+						 "cd %s; tar xf %s",
+						 userdir, anonproto);
+					system (cmdbuf);
+				}
+				if (strlen (anonpart) > 1) {
+					strcat (userdir, anonpart);
+					if (access (userdir, F_OK))
+						createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line);
+				}
+			}
+			free (userdir);
 		}
 
 		/*
